home *** CD-ROM | disk | FTP | other *** search
- /* DoListSCSIDevices.c */
- /*
- * DoListSCSIDevices.c
- * Copyright © 1992-94 Apple Computer Inc. All Rights Reserved.
- *
- * Find all SCSI devices. The alogrithm first asks the SCSI Manager for the
- * number of busses, then loops through each bus for each device and LUN.
- * old SCSI Manager. This is made complex by the flexible SCSI Manager 4.3
- * architecture: it is possible for the asynchronous SCSI Manager to only
- * be available on a third-party bus interface, for example. Because of this,
- * we must always scan the bus using the original SCSI Manager even if the
- * asynchronous manager is present.
- */
- #include "SCSISimpleSample.h"
-
- void
- DoListSCSIDevices(void)
- {
- OSErr status;
- unsigned short lastHostBus;
- unsigned short initiatorID;
- unsigned short bus;
- unsigned short targetID;
- unsigned short LUN;
- DeviceIdent scsiDevice;
- SCSIGetVirtualIDInfoPB scsiGetVirtualIDInfo;
- short deviceCount;
- unsigned short maxTarget;
- Boolean useAsynchManager;
- Str255 work;
-
- LOG("\pList all SCSI Devices");
- deviceCount = 0;
- /*
- * If we have the asynchronous SCSI Manager, find out how many busses
- * are present on this system. If not, force a "single bus" scan, since
- * DoSCSICommandWithSense ignores the hostBus information if it is
- * forced into "old-style" calls.
- */
- if (gEnableNewSCSIManager)
- status = SCSIGetHighHostBusAdaptor(&lastHostBus);
- else {
- status = noErr;
- lastHostBus = 0; /* Force one bus only */
- }
- if (status == noErr) {
- for (bus = 0; bus <= lastHostBus; bus++) {
- /*
- * Look at this SCSI bus. This would be a good place to allocate
- * the SCSIExecIO command block. In this sample, however, it's
- * allocated on each call to AsyncSCSI, though this is inefficient.
- * Note that it is possible to have busses with no devices. This
- * is true for Apple Macintosh models with two busses (such as
- * the Quadra 950 and PowerMac 8100). Also, if you install a
- * third-party bus adaptor that supports the asynchronous SCSI
- * Manager on a machine with two busses, it would be assigned
- * bus 2 (with busses 0 and 1 referencing the internal system
- * busses). In this case, a system could have no devices on bus
- * 0 or 1.
- */
- *((long *) &scsiDevice) = 0;
- scsiDevice.bus = bus;
- /*
- * Check whether we can access this scsi device. SCSIBusAPI will
- * return an error status if this bus is inaccessable (i.e. no bus
- * or other trouble). If it returns noErr, useAsyncManager will
- * be TRUE if the asynchronous SCSI Manager is supported for this
- * bus, and FALSE if it can only be accessed through the original
- * SCSI Manager. This would indicate that a third-party bus
- * interface patched the original SCSI Manager traps (i.e.,
- * patched SCSIGet, SCSISelect, etc).
- */
- status = SCSIBusAPI(scsiDevice, &useAsynchManager);
- if (status == noErr) {
- if (useAsynchManager)
- status = SCSIGetInitiatorID(scsiDevice, &initiatorID);
- else {
- initiatorID = 7; /* Asynch manager is disabled */
- }
- }
- if (status != noErr)
- continue;
- /*
- * SCSIGetInitiatorID returned the bus ID of the Macintosh. This
- * is almost always seven, but only the SCSI Manager knows for
- * sure. Note that, by getting the Macintosh bus ID dynamically,
- * we prepare the code for a future system that permitted more
- * than one Macintosh on the same SCSI bus.
- */
- status = SCSIGetMaxTargetID(scsiDevice, &maxTarget);
- for (targetID = 0; targetID <= maxTarget; targetID++) {
- if (targetID != initiatorID) {
- scsiDevice.targetID = targetID;
- for (LUN = 0; LUN <= gMaxLogicalUnit; LUN++) {
- /*
- * Try to send a command to this LUN. If it fails,
- * don't try for higher-valued LUNs.
- * SCSICheckForDevicePresent looks, carefully, at the
- * returned error to distinguish between missing
- * devices and devices that are present, but unable to
- * respond, such as CD-ROM players with no disk
- * inserted. This call to SCSICheckForDevicePresent
- * will use the asynchronous SCSI Manager if it can.
- *
- * Note that, if the asynchronous manager is not
- * available, we can still check for non-zero LUNs by
- * using the old method of stuffing the LUN into the
- * command block, however this is not supported in
- * this example.
- */
- scsiDevice.LUN = LUN;
- if (SCSICheckForDevicePresent(
- scsiDevice, useAsynchManager) == FALSE)
- break; /* Don't look for LUNs */
- else {
- ++deviceCount; /* Found a device */
- DoGetDriveInfo(scsiDevice, TRUE, useAsynchManager);
- } /* Check status */
- } /* LUN loop */
- } /* Not the initiator id */
- } /* Target loop */
- } /* Bus loop */
- /*
- * Now, we need to look at the hard-wired SCSI drive addresses and
- * check whether a third-party hardware interface that does not use
- * the asynchronous SCSI Manager recognizes this address. If
- * gEnableNewSCSIManager is FALSE, the above loop called the original
- * SCSI Manager, so we don't have to try it again. In this sequence,
- * we hard-wire the initiator ID to seven, as there is no supported
- * way to determine it from the SCSI Manager or operating system.
- */
- if (gEnableNewSCSIManager) {
- scsiDevice.bus = 0;
- for (targetID = 0; targetID <= 6; targetID++) {
- CLEAR(scsiGetVirtualIDInfo);
- scsiGetVirtualIDInfo.scsiPBLength = sizeof scsiGetVirtualIDInfo;
- scsiGetVirtualIDInfo.scsiOldCallID = targetID;
- status = SCSIAction((SCSI_PB *) &scsiGetVirtualIDInfo);
- if (status != noErr) {
- /*
- * The asynchronous SCSI Manager does not know about this
- * target ID. Check whether it exists (forcing the request
- * to use the original SCSI Manager).
- */
- scsiDevice.targetID = targetID;
- for (LUN = 0; LUN <= gMaxLogicalUnit; LUN++) {
- scsiDevice.LUN = LUN;
- if (SCSICheckForDevicePresent(scsiDevice, FALSE) == FALSE)
- break; /* Don't look for LUNs */
- else {
- ++deviceCount; /* Found a device */
- DoGetDriveInfo(scsiDevice, TRUE, FALSE);
- } /* Check status */
- }
- }
- }
- }
- } /* Found a host adaptor */
- NumToString(deviceCount, work);
- AppendPascalString(work, "\p SCSI Devices");
- LOG(work);
- }
-